﻿using MessagePack;
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace BinaryTest
{
    class Program
    {
        static void Main(string[] args)
        {
            TestBeetleX();
            Console.ReadLine();
        }




        static void TestBinary()
        {
            People bai = Whiter.New();
            Console.WriteLine(JsonConvert.SerializeObject(bai));
            var converter = new BinaryFormatter.BinaryConverter();
            byte[] data = converter.Serialize(bai);
            //System.InvalidCastException:“Unable to cast object of type 'BinaryTest.Whiter' to type 'BinaryTest.Blacker'.”
            //Blacker hei = converter.Deserialize<Blacker>(data);
            //Console.WriteLine(JsonConvert.SerializeObject(hei));
            //System.InvalidCastException:“Unable to cast object of type 'BinaryTest.Whiter' to type 'BinaryTest.Copy.Whiter'.”
            Copy.Whiter bai1 = converter.Deserialize<Copy.Whiter>(data);
            Console.WriteLine(JsonConvert.SerializeObject(bai1));
        }

        static void TestBeetleX()
        {
            MessagePackSerializer
             People bai = Whiter.New();
            string json = JsonConvert.SerializeObject(bai);
            Console.WriteLine(json);
            byte[] bytes = MessagePackSerializer.Serialize(bai);
            bai= MessagePackSerializer.Deserialize<Whiter>(bytes);
            json = JsonConvert.SerializeObject(bai);
            Console.WriteLine(json);
        }

        /// <summary>
        /// 会序列化公共字段、属性
        /// 只读公共属性、字段，也会被序列化成为JSON
        /// Newtonsoft.Json.JsonIgnore 特性可以阻止被序列化
        /// </summary>
        static void TestJson()
        {
            People bai = Whiter.New();
            string json = JsonConvert.SerializeObject(bai);
            Console.WriteLine(json);
            Blacker hei = JsonConvert.DeserializeObject<Blacker>(json);
            string json1 = JsonConvert.SerializeObject(hei);
            Console.WriteLine(json1);
        }

        static void TestSpeed()
        {
            int times = 1000;
            People bai = Whiter.New();
            Stopwatch stopwatch = new Stopwatch();

            SpeedOfBinaryFormatter(times, bai, stopwatch);
            SpeedOfJson(times, bai, stopwatch);
            SpeedOfMikodev(times, bai, stopwatch);
            SpeedOfBeetleX(times, bai, stopwatch);
        }

        static void SpeedOfMikodev(int times, People bai, Stopwatch stopwatch)
        {
            var generator = Mikodev.Binary.Generator.CreateDefault();
            stopwatch.Reset();
            stopwatch.Start();
            for (int i = 0; i < times; i++)
            {
                byte[] data= Mikodev.Binary.GeneratorExtensions.Encode(generator, bai);
                Mikodev.Binary.GeneratorExtensions.Decode(generator, data,anonymous:bai);
            }
            stopwatch.Stop();
            Console.WriteLine($"运行SpeedOfMikodev{times}次，耗时{stopwatch.ElapsedMilliseconds}ms");
        }

        static void SpeedOfBeetleX(int times, People bai, Stopwatch stopwatch)
        {
            stopwatch.Reset();
            stopwatch.Start();
            for (int i = 0; i < times; i++)
            {
                byte[] bytes = MessagePackSerializer.Serialize(bai);
                MessagePackSerializer.Deserialize<Whiter>(bytes);
            }
            stopwatch.Stop();
            Console.WriteLine($"运行SpeedOfBeetleX{times}次，耗时{stopwatch.ElapsedMilliseconds}ms");
        }
        private static void SpeedOfJson(int times, People bai, Stopwatch stopwatch)
        {
            stopwatch.Reset();
            stopwatch.Start();
            for (int i = 0; i < times; i++)
            {
                string json = JsonConvert.SerializeObject(bai);
                byte[] data = Encoding.UTF8.GetBytes(json);
                json = Encoding.UTF8.GetString(data);
                JsonConvert.DeserializeObject<Whiter>(json);
            }
            stopwatch.Stop();
            Console.WriteLine($"运行SpeedOfJson{times}次，耗时{stopwatch.ElapsedMilliseconds}ms");
        }

        private static void SpeedOfBinaryFormatter(int times, People bai, Stopwatch stopwatch)
        {
            var converter = new BinaryFormatter.BinaryConverter();
            stopwatch.Reset();
            stopwatch.Start();
            for (int i = 0; i < times; i++)
            {
                byte[] data = converter.Serialize(bai);
                converter.Deserialize<Whiter>(data);
            }
            stopwatch.Stop();
            Console.WriteLine($"运行SpeedOfBinaryFormatter{times}次，耗时{stopwatch.ElapsedMilliseconds}ms");
        }
    }

    //[MessagePack.MessagePackFormatter(typeof(ClassFormater<People>))]
    class People
    {
        public People()
        {
            ReadonlyToken = Guid.NewGuid().ToString();
        }
        public readonly string ReadonlyToken = null;
        public string Id { get; set; }

        [Newtonsoft.Json.JsonIgnore]
        public string Name { get; set; }

        public string Skin { get; set; }

        protected string ProtectedName { get; set; }

        public string Token = null;


        protected string ProtectedToken { get; set; }
    }

    //[MessagePack.MessagePackFormatter(typeof(ClassFormater<Blacker>))]
    class Blacker : People
    {

        public bool IsFeizhou { get; set; }

        public static People New()
        {
            return new Blacker()
            {
                Id = Guid.NewGuid().ToString()
                ,
                Name = Guid.NewGuid().ToString().Split('-').FirstOrDefault()
                ,
                Skin = "黑色"
                ,
                IsFeizhou = Guid.NewGuid().ToByteArray().FirstOrDefault() % 2 == 0
                ,
                Token = Guid.NewGuid().ToString()
                ,
                ProtectedToken = Guid.NewGuid().ToString()
                ,
                ProtectedName = Guid.NewGuid().ToString().Split('-').FirstOrDefault()
            };
        }
    }

    //[MessagePack.MessagePackFormatter(typeof(ClassFormater<Whiter>))]
    class Whiter : People
    {
        public bool IsEngland { get; set; }

        public static People New()
        {
            return new Whiter()
            {
                Id = Guid.NewGuid().ToString()
                ,
                Name = Guid.NewGuid().ToString().Split('-').FirstOrDefault()
                ,
                Skin = "白色"
                ,
                IsEngland = Guid.NewGuid().ToByteArray().FirstOrDefault() % 10 == 0
                ,
                Token = Guid.NewGuid().ToString()
                ,
                ProtectedToken = Guid.NewGuid().ToString()
                ,
                ProtectedName = Guid.NewGuid().ToString().Split('-').FirstOrDefault()
            };
        }
    }

}

namespace BinaryTest.Copy
{
    class Whiter : BinaryTest.Whiter
    {

    }
}
